﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace IoTCM
{
    public class XmlSerializer : IObjectSerializer
    {
        public string Serialize(IEnumerable<Thing> things)
        {
            var element = new XElement("Things");

            if (things != null)
            {
                foreach (var t in things)
                {
                    element.Add(Serialize(t));
                }
            }

            return element.ToString();
        }

        public string Serialize(IEnumerable<DataItem> data)
        {
            var element = new XElement("Data");

            if (data != null)
            {
                foreach (var d in data)
                {
                    element.Add(Serialize(d));
                }
            }

            return element.ToString();
        }

        private XElement Serialize(DataItem data)
        {
            // serialize the required properties
            var element = new XElement("Data",
                new XAttribute("id", data.ID),
                new XAttribute("dataType", data.DataType),
                new XAttribute("writable", data.Writable));


            // serialize the optional properties
            if (!string.IsNullOrEmpty(data.Units))
            {
                element.Add(new XAttribute("units", data.Units));
            }

            if (!string.IsNullOrEmpty(data.StandardDataID))
            {
                element.Add(new XAttribute("standardDataID", data.StandardDataID));
            }

            return element;
        }

        public string Serialize(Thing thing)
        {
            if (thing == null) return null;

            // serialize the required properties
            var element = new XElement("Thing",
                new XAttribute("id", thing.ID),
                new XAttribute("instance", thing.Instance));


            // serialize the optional properties
            if (!string.IsNullOrEmpty(thing.Name))
            {
                element.Add(new XAttribute("name", thing.Name));
            }

            if (!string.IsNullOrEmpty(thing.StandardThingID))
            {
                element.Add(new XAttribute("standardThingID", thing.StandardThingID));
            }

            // serialize any Data
            if (thing.HasData())
            {
                element.Add(Serialize(thing.Items));
            }

            // serialize any children

            if (thing.HasThings())
            {
                element.Add(Serialize(thing.Things));
            }

            return element.ToString();
        }

        public string Serialize(DataValueCollection values)
        {
            var element = new XElement("Values",
                new XAttribute("timestamp", values.Timestamp.ToString("s")),
                new XAttribute("instance", values.Instance));

            foreach (var value in values)
            {
                element.Add(Serialize(value));
            }

            return element.ToString();
        }

        private XElement Serialize(DataValue value)
        {
            return new XElement("Value",
                new XAttribute("id", value.ID),
                value.Value);
        }

        public IEnumerable<DataValue> DeserializeValues(string serializedValues)
        {
            var element = XElement.Parse(serializedValues);

            if (element.Name != "Values") throw new ArgumentException("Expected Values list");

            var values = from e in element.Elements("Value")
                         select new DataValue()
                         {
                             ID = (string)e.Attribute("id"),
                             Value = e.Value
                         };

            return values;
        }
    }
}
